package com.smedi.ismedi.web.starter.async;

import com.smedi.ismedi.authority.starter.constant.WebParameterConstant;
import com.smedi.ismedi.web.starter.property.FeignHeaderForwardProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.concurrent.Callable;

@Slf4j
public class ContextAwareCallable<T> implements Callable<T> {
    @Autowired
    FeignHeaderForwardProperty feignHeaderForwardProperty;

    private Callable<T> task;

    private RequestAttributes context;

    /**
     * 转发请求时拥有特殊标记的属性
     *
     * @param context
     * @param session
     */
    private void reForwardAttribute(RequestAttributes context, HttpSession session) {
        log.info("通过ContextAwareCallable转发配置信息->");
        log.info("请求session参数: ");
        new ArrayList<String>() {{
            add(WebParameterConstant.prefix);
        }}.stream().forEach(prefix -> {
            Enumeration<String> enumerations = session.getAttributeNames();
            while (enumerations.hasMoreElements()) {
                String attribute = enumerations.nextElement();
                if (attribute.indexOf(prefix) >= 0) {
                    context.setAttribute(attribute, session.getAttribute(attribute), WebParameterConstant.requestScope);
                    log.info(" --- attribute: {}, value: {}", attribute, session.getAttribute(attribute));
                }
            }
        });
    }

    public ContextAwareCallable(Callable<T> task, RequestAttributes context) {
        this.task = task;
        this.context = context;
        // 转发
        reForwardAttribute(this.context, ((ServletRequestAttributes) context).getRequest().getSession());
    }

    @Override
    public T call() throws Exception {
        if (context != null) {
            RequestContextHolder.setRequestAttributes(context);
        }
        try {
            return task.call();
        } finally {
            RequestContextHolder.resetRequestAttributes();
        }
    }
}